home *** CD-ROM | disk | FTP | other *** search
/ BBS in a Box 3 / BBS in a box - Trilogy III.iso / Files / System7 tools / Frontier / Frontier SDK 2.1 / Toolkits / Applet Toolkit / appletscrollbar.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-10-11  |  16.4 KB  |  862 lines  |  [TEXT/KAHL]

  1.  
  2. /*© Copyright 1988-1992 UserLand Software, Inc.  All Rights Reserved.*/
  3.  
  4.  
  5. #include "appletinternal.h"
  6. #include "appletops.h"
  7. #include "appletquickdraw.h"
  8. #include "appletmain.h"
  9. #include "appletscrollbar.h"
  10.  
  11.  
  12.  
  13. #define idvertbar 256
  14. #define idhorizbar 257
  15.  
  16.  
  17. static boolean scrollbarpushclip (hdlscrollbar hscrollbar) {
  18.     
  19.     /*
  20.     11/19/90 DW: patch things up for the table displayer, and perhaps others in
  21.     the future.  if the scrollbar is of trivial height, we disable the drawing
  22.     that's about to happen.  we were getting one-pixel high scrollbars being
  23.     drawn.
  24.     */
  25.     
  26.     Rect r = (**hscrollbar).contrlRect;
  27.     
  28.     if ((r.bottom - r.top) == 1)
  29.         r.bottom = r.top;
  30.         
  31.     return (pushclip (r));
  32.     } /*scrollbarpushclip*/
  33.     
  34.     
  35. void validscrollbar (hdlscrollbar hscrollbar) {
  36.  
  37.     register hdlscrollbar h = hscrollbar;
  38.     
  39.     if (h != nil) 
  40.         validrect ((**h).contrlRect);
  41.     } /*validscrollbar*/
  42.     
  43.     
  44. void invalscrollbar (hdlscrollbar hscrollbar) {
  45.  
  46.     register hdlscrollbar h = hscrollbar;
  47.     
  48.     if (h != nil) 
  49.         invalrect ((**h).contrlRect);
  50.     } /*invalscrollbar*/
  51.     
  52.     
  53. boolean pointinscrollbar (Point pt, hdlscrollbar hscrollbar) {
  54.  
  55.     register hdlscrollbar h = hscrollbar;
  56.     
  57.     if (h == nil) /*defensive driving*/
  58.         return (false);
  59.         
  60.     return (pointinrect (pt, (**h).contrlRect));
  61.     } /*pointinscrollbar*/
  62.     
  63.     
  64. void disablescrollbar (hdlscrollbar hscrollbar) {
  65.     
  66.     register hdlscrollbar h = hscrollbar;
  67.     
  68.     if (h == nil) /*defensive driving*/
  69.         return;
  70.         
  71.     scrollbarpushclip (h);
  72.         
  73.     HiliteControl (h, -1);
  74.     
  75.     /*validscrollbar (h);*/
  76.     
  77.     popclip ();
  78.     } /*disablescrollbar*/
  79.     
  80.     
  81. void enablescrollbar (hdlscrollbar hscrollbar) {
  82.     
  83.     register hdlscrollbar h = hscrollbar;
  84.     
  85.     if (h == nil) /*defensive driving*/
  86.         return;
  87.         
  88.     if (!(**h).contrlRfCon) { /*the window containing the scrollbar is inactive*/
  89.         
  90.         disablescrollbar (h);
  91.         
  92.         return;
  93.         }
  94.         
  95.     scrollbarpushclip (h);
  96.         
  97.     HiliteControl (h, 0);
  98.     
  99.     /*validscrollbar (h);*/
  100.     
  101.     popclip ();
  102.     } /*enablescrollbar*/
  103.     
  104.     
  105. boolean scrollbarenabled (hdlscrollbar hscrollbar) {
  106.     
  107.     return ((**hscrollbar).contrlHilite != 255);
  108.     } /*scrollbarenabled*/
  109.     
  110.     
  111. void activatescrollbar (hdlscrollbar hscrollbar, boolean flactivate) {
  112.     
  113.     /*
  114.     8/25/92 DW: use the contrlRfCon field to indicate whether the 
  115.     scrollbar is active or not. this flag is respected by subsequent calls
  116.     to enablescrollbar.
  117.     */
  118.     
  119.     hdlscrollbar h = hscrollbar;
  120.     
  121.     (**h).contrlRfCon = flactivate;
  122.     
  123.     if (flactivate)
  124.         enablescrollbar (h);
  125.     else
  126.         disablescrollbar (h);
  127.     } /*activatescrollbar*/
  128.     
  129.     
  130. void getscrollbarinfo (hscrollbar, minscroll, maxscroll, current) hdlscrollbar hscrollbar; short *minscroll, *maxscroll, *current; {
  131.     
  132.     register hdlscrollbar h = hscrollbar;
  133.     
  134.     if (h == nil) { /*defensive driving*/
  135.     
  136.         *minscroll = *maxscroll = *current = 0;
  137.         
  138.         return;
  139.         }
  140.     
  141.     *minscroll = GetCtlMin (h);
  142.         
  143.     *maxscroll = GetCtlMax (h);
  144.         
  145.     *current = GetCtlValue (h);
  146.     } /*getscrollbarinfo*/
  147.     
  148.     
  149. short getscrollbarcurrent (hdlscrollbar hscrollbar) {
  150.     
  151.     short minscroll, maxscroll, current;
  152.     
  153.     getscrollbarinfo (hscrollbar, &minscroll, &maxscroll, ¤t);
  154.     
  155.     return (current);
  156.     } /*getscrollbarcurrent*/
  157.     
  158.     
  159. void showscrollbar (hdlscrollbar hscrollbar) {
  160.     
  161.     register hdlscrollbar h = hscrollbar;
  162.     
  163.     if (h == nil) /*defensive driving*/
  164.         return;
  165.         
  166.     scrollbarpushclip (h);
  167.         
  168.     ShowControl (h); /*no effect if scrollbar is already visible, according to IM-1*/
  169.     
  170.     popclip ();
  171.     
  172.     /*don't validate the scrollbar rect, ShowControl might not draw it...*/
  173.     } /*showscrollbar*/
  174.     
  175.     
  176. void hidescrollbar (hdlscrollbar hscrollbar) {
  177.     
  178.     register hdlscrollbar h = hscrollbar;
  179.     
  180.     if (h == nil) /*defensive driving*/
  181.         return;
  182.         
  183.     scrollbarpushclip (h);
  184.         
  185.     HideControl (h);
  186.     
  187.     popclip ();
  188.     
  189.     invalrect ((**h).contrlRect);
  190.     } /*hidescrollbar*/
  191.     
  192.  
  193. void drawscrollbar (hdlscrollbar hscrollbar) {
  194.     
  195.     register hdlscrollbar h = hscrollbar;
  196.     
  197.     if (h == nil) /*defensive driving*/
  198.         return;
  199.         
  200.     scrollbarpushclip (h);
  201.     
  202.     Draw1Control (h);
  203.     
  204.     popclip ();
  205.     
  206.     validscrollbar (h);
  207.     } /*drawscrollbar*/
  208.     
  209.     
  210. void displayscrollbar (hdlscrollbar hscrollbar) {
  211.     
  212.     /*
  213.     the caller is saying that we should enable it if there is enough 
  214.     material to enable scrolling.
  215.     */
  216.     
  217.     register hdlscrollbar h = hscrollbar;
  218.     short minscroll, maxscroll, current;
  219.     
  220.     if (h == nil) /*defensive driving*/
  221.         return;
  222.         
  223.     getscrollbarinfo (h, &minscroll, &maxscroll, ¤t);
  224.     
  225.     if (minscroll <= maxscroll) /*there's something to scroll to*/
  226.         enablescrollbar (h);
  227.     else
  228.         disablescrollbar (h);
  229.         
  230.     drawscrollbar (h);
  231.     } /*displayscrollbar*/
  232.     
  233.     
  234. void setscrollbarinfo (hdlscrollbar hscrollbar, short minscroll, short maxscroll, short current) {
  235.     
  236.     /*
  237.     set the bounds of the scrollbar, and its current value.
  238.     
  239.     if the current info agrees with the parameters we do nothing, 
  240.     avoiding unpleasant flicker.
  241.     
  242.     disables drawing while setting the values, and draws it when 
  243.     all three values have been set.  avoids inconsistent displays.
  244.     */
  245.     
  246.     register hdlscrollbar h = hscrollbar;
  247.     short curmin, curmax, curval;
  248.     
  249.     if (h == nil) /*defensive driving*/
  250.         return;
  251.     
  252.     getscrollbarinfo (h, &curmin, &curmax, &curval);
  253.     
  254.     if ((minscroll == curmin) && (maxscroll == curmax) && (current == curval))
  255.         return; /*nothing to do*/
  256.     
  257.     pushemptyclip (); /*disable drawing*/
  258.     
  259.     SetCtlMax (h, maxscroll);
  260.     
  261.     SetCtlMin (h, minscroll);
  262.     
  263.     SetCtlValue (h, current);
  264.     
  265.     popclip ();
  266.     
  267.     displayscrollbar (h);
  268.     } /*setscrollbarinfo*/
  269.     
  270.     
  271. void setscrollbarminmax (hdlscrollbar hscrollbar, short minscroll, short maxscroll) {
  272.     
  273.     register hdlscrollbar h = hscrollbar;
  274.     short curmin, curmax, curval;
  275.     
  276.     if (h == nil) /*defensive driving*/
  277.         return;
  278.     
  279.     getscrollbarinfo (h, &curmin, &curmax, &curval);
  280.     
  281.     if ((minscroll != curmin) || (maxscroll != curmax)) {
  282.     
  283.         setscrollbarinfo (h, minscroll, maxscroll, curval);
  284.         }
  285.     } /*setscrollbarminmax*/
  286.     
  287.     
  288. void setscrollbarcurrent (hdlscrollbar hscrollbar, short current) {
  289.  
  290.     register hdlscrollbar h = hscrollbar;
  291.     
  292.     if (h == nil) /*defensive driving*/
  293.         return;
  294.     
  295.     scrollbarpushclip (h);
  296.     
  297.     SetCtlValue (h, current);
  298.     
  299.     popclip ();
  300.     } /*setscrollbarcurrent*/
  301.  
  302.  
  303. short getscrollbarwidth (void) {
  304.     
  305.     return (16); /*standard Macintosh scrollbars*/
  306.     } /*getscrollbarwidth*/
  307.  
  308.  
  309. boolean newscrollbar (WindowPtr w, boolean flvert, hdlscrollbar *hscrollbar) {
  310.     
  311.     /*
  312.     create a new scroll bar linked into the control list of the indicated
  313.     window.  
  314.     
  315.     we need to know if it is a vertical or horizontal scrollbar so we can
  316.     choose the proper resource template.  we use a CDEF that has different
  317.     specs for horiz and vertical scrollbars.
  318.     */
  319.     
  320.     register hdlscrollbar h;
  321.     register short resnum;
  322.     
  323.     if (flvert)
  324.         resnum = idvertbar;
  325.     else
  326.         resnum = idhorizbar;
  327.     
  328.     *hscrollbar = h = GetNewControl (resnum, w);
  329.     
  330.     return (h != nil);
  331.     } /*newscrollbar*/
  332.     
  333.     
  334. void disposescrollbar (hdlscrollbar hscrollbar) {
  335.     
  336.     register hdlscrollbar h = hscrollbar;
  337.     
  338.     if (h != nil)
  339.         DisposeControl (h);
  340.     } /*disposescrollbar*/
  341.     
  342.     
  343. void getscrollbarrect (hdlscrollbar hscrollbar, Rect *r) {
  344.  
  345.     register hdlscrollbar h = hscrollbar;
  346.     
  347.     if (h != nil) 
  348.         *r = (**h).contrlRect;
  349.     else
  350.         zerorect (r);
  351.     } /*getscrollbarrect*/
  352.     
  353.     
  354. void setscrollbarrect (hdlscrollbar hscrollbar, Rect r) {
  355.  
  356.     register hdlscrollbar h = hscrollbar;
  357.     
  358.     if (h != nil) {
  359.         
  360.         HideControl (h);
  361.         
  362.         SizeControl (h, r.right - r.left, r.bottom - r.top);
  363.         
  364.         MoveControl (h, r.left, r.top);
  365.         }
  366.     } /*setscrollbarrect*/
  367.     
  368.     
  369. void scrollbarflushright (Rect r, hdlscrollbar hscrollbar) {
  370.     
  371.     register hdlscrollbar h = hscrollbar;
  372.     register short width;
  373.     
  374.     if (h == nil) /*defensive driving*/
  375.         return;
  376.         
  377.     width = getscrollbarwidth ();
  378.     
  379.     HideControl (h);
  380.     
  381.     SizeControl (h, width, r.bottom - r.top + 2);
  382.     
  383.     MoveControl (h, r.right - width + 1, r.top - 1);
  384.     } /*scrollbarflushright*/
  385.     
  386.     
  387. void scrollbarflushbottom (Rect r, hdlscrollbar hscrollbar) {
  388.     
  389.     register hdlscrollbar h = hscrollbar;
  390.     register short width;
  391.     
  392.     if (h == nil) /*defensive driving*/
  393.         return;
  394.         
  395.     width = getscrollbarwidth ();
  396.         
  397.     HideControl (h);
  398.     
  399.     SizeControl (hscrollbar, r.right - r.left, width);
  400.         
  401.     MoveControl (hscrollbar, r.left, r.bottom - width + 1);
  402.     } /*scrollbarflushbottom*/
  403.     
  404.     
  405. boolean findscrollbar (Point pt, WindowPtr w, hdlscrollbar *hscrollbar, short *scrollbarpart) {
  406.     
  407.     *scrollbarpart = FindControl (pt, w, hscrollbar);
  408.     
  409.     return (*hscrollbar != nil);
  410.     } /*findscrollbar*/
  411.     
  412.     
  413. boolean scrollbarhit (hdlscrollbar hscrollbar, short part, boolean *flup, boolean *flpage) {
  414.     
  415.     /*
  416.     can be called by a routine that tracks a mouse hit in a scroll bar.
  417.     
  418.     return true if it represents a valid scroll action, according to the info
  419.     stored in the scrollbar handle.
  420.     
  421.     return false if the indicated action would move beyond the min or max for
  422.     the scrollbar.
  423.     
  424.     set flup and flpage according to the indicated scrollbar part.
  425.     */
  426.     
  427.     register hdlscrollbar h = hscrollbar;
  428.     short minscroll, maxscroll, current;
  429.     
  430.     if (h == nil) /*defensive driving*/
  431.         return;
  432.         
  433.     getscrollbarinfo (h, &minscroll, &maxscroll, ¤t);
  434.     
  435.     switch (part) {
  436.     
  437.         case inUpButton:
  438.             *flup = false; /*scroll text down*/
  439.             
  440.             *flpage = false;
  441.             
  442.             return (current > minscroll);
  443.             
  444.         case inDownButton:
  445.             *flup = true; /*scroll text up*/
  446.             
  447.             *flpage = false;
  448.             
  449.             return (current < maxscroll);
  450.             
  451.         case inPageUp:
  452.             *flup = false; /*scroll text down*/
  453.             
  454.             *flpage = true; 
  455.             
  456.             return (current > minscroll);
  457.             
  458.         case inPageDown:
  459.             *flup = true; /*scroll text up*/
  460.             
  461.             *flpage = true;
  462.             
  463.             return (current < maxscroll);
  464.         } /*switch*/
  465.         
  466.     return (false); /*fell through the switch statement*/
  467.     } /*scrollbarhit*/
  468.     
  469.  
  470. void resetappscrollbars (hdlappwindow appwindow) {
  471.         
  472.     hdlappwindow ha = appwindow;
  473.     Rect r, rcontent;
  474.     short vertmin, vertmax, vertcurrent;    
  475.     short horizmin, horizmax, horizcurrent;
  476.     
  477.     setappwindow (ha);
  478.     
  479.     appprecallback ();
  480.         
  481.     (*app.getcontentsizecallback) ();
  482.     
  483.     apppostcallback ();
  484.     
  485.     getscrollbarinfo ((**ha).vertbar, &vertmin, &vertmax, &vertcurrent);
  486.     
  487.     getscrollbarinfo ((**ha).horizbar, &horizmin, &horizmax, &horizcurrent);
  488.     
  489.     rcontent = (**ha).contentrect;
  490.     
  491.     /*reset the vertical scrollbar*/ {
  492.         
  493.         short needpixels = (**ha).zoomheight;
  494.         short havepixels = rcontent.bottom - rcontent.top;
  495.         hdlscrollbar bar = (**ha).vertbar;
  496.         
  497.         if (havepixels >= needpixels) {
  498.             
  499.             disablescrollbar (bar);
  500.             
  501.             /*setscrollbarinfo (bar, 0, 0, 0);*/
  502.             }
  503.         else {
  504.             short x = 0;
  505.             
  506.             enablescrollbar (bar);
  507.             
  508.             vertmin = 0;
  509.             
  510.             vertmax = needpixels - havepixels;
  511.             }
  512.         }
  513.         
  514.     /*reset the horiz scrollbar*/ {
  515.         
  516.         short needpixels = (**ha).zoomwidth;
  517.         short havepixels = rcontent.right - rcontent.left;
  518.         hdlscrollbar bar = (**ha).horizbar;
  519.         
  520.         if (havepixels >= needpixels) {
  521.             
  522.             disablescrollbar (bar);
  523.             
  524.             /*setscrollbarinfo (bar, 0, 0, 0);*/
  525.             }
  526.         else {
  527.             short x = 0;
  528.             
  529.             enablescrollbar (bar);
  530.             
  531.             horizmin = 0;
  532.             
  533.             horizmax = needpixels - havepixels;
  534.             }
  535.         }
  536.     
  537.     setscrollbarinfo ((**ha).vertbar, vertmin, vertmax, vertcurrent);
  538.     
  539.     setscrollbarinfo ((**ha).horizbar, horizmin, horizmax, horizcurrent);
  540.     } /*resetappscrollbars*/
  541.     
  542.  
  543. void resizeappscrollbars (appwindow) hdlappwindow appwindow; {
  544.     
  545.     if (app.horizscroll || app.vertscroll) {
  546.         
  547.         register hdlappwindow ha = appwindow;
  548.         register short scrollbarwidth;
  549.         Rect rwholewindow = (**ha).windowrect;
  550.         Rect r;
  551.         
  552.         scrollbarwidth = getscrollbarwidth ();
  553.     
  554.         if (app.vertscroll) {
  555.     
  556.             r = rwholewindow; 
  557.         
  558.             r.bottom -= scrollbarwidth - 1;
  559.             
  560.             r.top += app.statuspixels; /*leave room for status bar at top of window*/
  561.             
  562.             r.top = (**ha).contentrect.top;
  563.         
  564.             scrollbarflushright (r, (**ha).vertbar);
  565.             }
  566.         
  567.         if (app.horizscroll) {
  568.         
  569.             r = rwholewindow; 
  570.         
  571.             r.right -= scrollbarwidth - 2;
  572.         
  573.             r.left -= 1; 
  574.             
  575.             scrollbarflushbottom (r, (**ha).horizbar);
  576.             }
  577.         }
  578.     } /*resizeappscrollbars*/
  579.     
  580.     
  581. void showappscrollbars (appwindow) hdlappwindow appwindow; {
  582.     
  583.     register hdlappwindow ha = appwindow;
  584.     
  585.     if (app.vertscroll)
  586.         showscrollbar ((**ha).vertbar);
  587.     
  588.     if (app.horizscroll)
  589.         showscrollbar ((**ha).horizbar);
  590.     } /*showappscrollbars*/
  591.     
  592.     
  593. void updateappscrollbars (appwindow) hdlappwindow appwindow; {
  594.     
  595.     register hdlappwindow ha = appwindow;
  596.         
  597.     if (app.vertscroll) {
  598.         
  599.         showscrollbar ((**ha).vertbar);
  600.         
  601.         drawscrollbar ((**ha).vertbar);
  602.         }
  603.         
  604.     if (app.horizscroll) {
  605.         
  606.         showscrollbar ((**ha).horizbar);
  607.         
  608.         drawscrollbar ((**ha).horizbar);
  609.         }
  610.     } /*updateappscrollbars*/
  611.     
  612.     
  613. void activateappscrollbars (appwindow, flactivate) hdlappwindow appwindow; boolean flactivate; {
  614.     
  615.     register hdlappwindow ha = appwindow;
  616.     
  617.     if (app.vertscroll)     
  618.         activatescrollbar ((**ha).vertbar, flactivate);
  619.         
  620.     if (app.horizscroll)     
  621.         activatescrollbar ((**ha).horizbar, flactivate);
  622.     } /*activateappscrollbars*/
  623.     
  624.     
  625. tydirection scrolldirection (boolean flvert, boolean flup) {
  626.  
  627.     register tydirection dir;
  628.     
  629.     if (flvert) {
  630.         if (flup)
  631.             dir = up;
  632.         else
  633.             dir = down;
  634.         }
  635.     else {
  636.         if (flup)
  637.             dir = left;
  638.         else
  639.             dir = right; 
  640.         }
  641.         
  642.     return (dir);
  643.     } /*scrolldirection*/ 
  644.  
  645.  
  646. boolean scrollappwindow (tydirection dir, boolean flpage, short ctscroll) {
  647.  
  648.     appprecallback ();
  649.         
  650.     (*app.scrollcallback) (dir, flpage, 1);
  651.     
  652.     apppostcallback ();
  653.     } /*scrollappwindow*/
  654.     
  655.  
  656. boolean scrolltoappwindow (void) {
  657.  
  658.     appprecallback ();
  659.     
  660.     (*app.scrolltocallback) ();
  661.     
  662.     apppostcallback ();
  663.     } /*scrolltoappwindow*/
  664.     
  665.         
  666. static pascal void apphorizscroll (hdlscrollbar ctrl, short part) {
  667.     
  668.     register tydirection dir;
  669.     boolean flleft, flpage;
  670.     
  671.     if (!scrollbarhit (ctrl, part, &flleft, &flpage))
  672.         return;
  673.         
  674.     dir = scrolldirection (false, flleft);
  675.         
  676.     scrollappwindow (dir, flpage, 1);
  677.     } /*apphorizscroll*/
  678.  
  679.  
  680. static pascal void appvertscroll (hdlscrollbar sb, short part) {
  681.     
  682.     register tydirection dir;
  683.     boolean flup, flpage;
  684.     
  685.     if (!scrollbarhit (sb, part, &flup, &flpage))
  686.         return;
  687.     
  688.     dir = scrolldirection (true, flup);
  689.         
  690.     scrollappwindow (dir, flpage, 1);
  691.     } /*appvertscroll*/
  692.  
  693.  
  694. void handlescrollbar (boolean flvert, hdlscrollbar sb, short part, Point pt) {
  695.     
  696.     register short oldscrollbarcurrent;
  697.     register short ctscroll;
  698.     tydirection dir;
  699.     
  700.     if (part == inThumb) {
  701.         
  702.         oldscrollbarcurrent = getscrollbarcurrent (sb);
  703.         
  704.         scrollbarpushclip (sb);
  705.         
  706.         TrackControl (sb, pt, nil);
  707.             
  708.         popclip ();
  709.         
  710.         scrolltoappwindow ();
  711.         
  712.         /*
  713.         ctscroll = getscrollbarcurrent (sb) - oldscrollbarcurrent;
  714.         
  715.         dir = scrolldirection (flvert, ctscroll > 0);
  716.         
  717.         (*app.scrollcallback) (dir, false, abs (ctscroll));
  718.         */
  719.         }
  720.     else {
  721.         scrollbarpushclip (sb);
  722.         
  723.         if (flvert)
  724.             TrackControl (sb, pt, &appvertscroll);
  725.         else
  726.             TrackControl (sb, pt, &apphorizscroll);
  727.             
  728.         popclip ();
  729.         }
  730.     } /*handlescrollbar*/
  731.     
  732.     
  733. static boolean defaultscroll (tydirection dir, boolean flpage, short ctscroll) {
  734.     
  735.     /*
  736.     if the applet didn't define a scrolling routine, this routine will
  737.     be called to do the scrolling. it implements a very bare-bones way
  738.     of scrolling, that often is just what you want... in order for this
  739.     to work, the app must define a scrollto callback routine.
  740.     */
  741.     
  742.     register hdlappwindow ha = app.appwindow;
  743.     register short ct = ctscroll;
  744.     register short dh = 0, dv = 0;
  745.     Rect r;
  746.     
  747.     if ((ct == 1) && (!flpage)) { /*it's heuristic time!*/
  748.         
  749.         if (!optionkeydown ()) {
  750.             
  751.             ct = getfontheight (); /*scroll by this (reasonable) amount*/
  752.             
  753.             /*user holds down the option key to get a 2-pixel scroll*/
  754.             }
  755.         }
  756.     
  757.     if (ct % 2) /*it's an odd number*/
  758.         ct++;
  759.     
  760.     r = (**ha).contentrect;
  761.     
  762.     switch (dir) {
  763.         
  764.         case down:
  765.             if (flpage)
  766.                 dv = -(r.bottom - r.top);
  767.             else
  768.                 dv = -ct;
  769.             
  770.             break;
  771.             
  772.         case up:
  773.             if (flpage)
  774.                 dv = r.bottom - r.top;
  775.             else
  776.                 dv = ct;
  777.             
  778.             break;
  779.         
  780.         case right:
  781.             if (flpage)
  782.                 dh = -(r.right - r.left);
  783.             else
  784.                 dh = -ct;
  785.                 
  786.             break;
  787.             
  788.         case left:
  789.             if (flpage)
  790.                 dh = r.right - r.left;
  791.             else
  792.                 dh = ct;
  793.                 
  794.             break;
  795.             
  796.         default:
  797.             return (false);
  798.         } /*switch*/
  799.     
  800.     if ((dv != 0) && scrollbarenabled ((**ha).vertbar)) {
  801.         
  802.         register short x;
  803.         short vertmin, vertmax, vertcurrent;
  804.         
  805.         getscrollbarinfo ((**ha).vertbar, &vertmin, &vertmax, &vertcurrent);
  806.         
  807.         x = vertcurrent + dv;
  808.     
  809.         x = max (x, vertmin);
  810.     
  811.         x = min (x, vertmax);
  812.         
  813.         dv = vertcurrent - x;
  814.         
  815.         vertcurrent = x;
  816.         
  817.         setscrollbarinfo ((**ha).vertbar, vertmin, vertmax, vertcurrent);
  818.         }
  819.     
  820.     if ((dh != 0) && scrollbarenabled ((**ha).horizbar)) {
  821.         
  822.         register short x;
  823.         short horizmin, horizmax, horizcurrent;
  824.         
  825.         getscrollbarinfo ((**ha).horizbar, &horizmin, &horizmax, &horizcurrent);
  826.         
  827.         x = horizcurrent + dh;
  828.     
  829.         x = max (x, horizmin);
  830.     
  831.         x = min (x, horizmax);
  832.         
  833.         dh = horizcurrent - x;
  834.         
  835.         horizcurrent = x;
  836.         
  837.         setscrollbarinfo ((**ha).horizbar, horizmin, horizmax, horizcurrent);
  838.         }
  839.     
  840.     if ((dh != 0) || (dv != 0)) {
  841.         
  842.         scrolltoappwindow ();
  843.         
  844.         /*
  845.         scrollrect (r, dh, dv);
  846.     
  847.         updateappwindow (ha);
  848.         */
  849.         }
  850.         
  851.     return (true);
  852.     } /*defaultscroll*/
  853.     
  854.     
  855. void installscroll (void) {
  856.     
  857.     if ((app.scrollcallback == nil) && ((app.horizscroll) || (app.vertscroll)))
  858.         app.scrollcallback = &defaultscroll;
  859.     } /*installscroll*/
  860.     
  861.     
  862.